home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / std / c++ / 156 < prev    next >
Encoding:
Text File  |  1996-08-06  |  6.4 KB  |  138 lines

  1. Newsgroups: comp.std.c++
  2. Path: cs.mu.OZ.AU!bounce-back
  3. From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
  4. Subject: Re: Give operator. a chance
  5. Message-ID: <9601281318.9776@mulga.cs.mu.OZ.AU>
  6. Originator: fjh@munta.cs.mu.OZ.AU
  7. Sender: news@cs.mu.OZ.AU (CS-Usenet)
  8. Organization: Computer Science, University of Melbourne, Australia
  9. References: <3102AD11.1663@et.se> <4e8g4t$aa3@hermes.synopsys.com> <4easfd$puc@news2.delphi.com>
  10. X-Original-Date: Mon, 29 Jan 1996 00: 18:14 +1100
  11. Date: Sun, 28 Jan 1996 23:58:45 GMT
  12. Approved: fjh@cs.mu.oz.au
  13. X-Auth: PGPMoose V1.1 PGP comp.std.c++
  14.     iQBFAgUBMQwObuEDnX0m9pzZAQFk9QF8Cf/vu/js/KtVsANEP/lg2g/40bF8hNwO
  15.     B/mrmEb51NBiYn9HHZVwGbj3Cvy1ugk6
  16.     =5ilC
  17.  
  18. jodle@bix.com (jodle) writes:
  19.  
  20. >I'm afraid there is something I don't understand about this approach.  For
  21. >a nontrivial class, one in which you have a delegate pointer and other
  22. >members, how would you propose the compiler discriminate between
  23. >overloaded (delegative) member selection and the selection of actual
  24. >members of the class?  This would become an issue as soon as a member
  25. >function tries to access member data or a user of the class attempts to
  26. >form a call to a member function.
  27.  
  28. Jim Adcock proposed that if `.' was overloaded, then `.' always meant
  29. the overloaded version, not the built-in version.  That's what I
  30. implemented.  I think these simple semantics are quite sufficient to
  31. achieve the desired functionality.  Here's the documentation included
  32. in the gcc patch I previously posted, which explains how the problem
  33. you refer to can be solved.
  34.  
  35. -----------------------------------------------------------------------------
  36.  
  37. Overloading Operator Dot for Smart References
  38. =============================================
  39.  
  40.    Just as standard C++ allows you to overload `operator->()' to create
  41. "Smart Pointer" classes, GNU C++ allows you to overload `operator.()'
  42. to create "Smart Reference" classes.
  43.  
  44.    Overloading `operator->()' or `operator.()' is different to
  45. overloading the other binary operators, because the right hand operand
  46. is a field name, not an expression.  The overloaded operator function
  47. takes only a single argument, the left hand operand, and returns a
  48. pointer (for `operator->()') or a reference (for `operator.()') which
  49. the compiler then uses in combination with the field name to produce
  50. the final result.  Essentially, overloading operator dot is exactly the
  51. same as overloading operator arrow except that where operator arrow
  52. uses pointers, operator dot uses references.
  53.  
  54.    For any class X which overloads the dot operator, the compiler
  55. replaces all expressions of the form `x.m' with `(x.operator.()).m'.
  56. If the result of `X::operator.()' is a class type which also overloads
  57. dot, then the result is recursively subject to the same expansion.
  58. (Note that the first dot in `x.operator.()' is meant to represent the
  59. builtin operator dot and is not subject to recursive expansion, for
  60. otherwise we would get an infinite regress.)
  61.  
  62.    The overloaded `operator.()' will be invoked only when there is an
  63. actual dot operator present in the source code. If a member function is
  64. invoked without using a dot operator, then `operator.()' will *not* be
  65. invoked.  Conversely, a dot expression *always* invokes the appropriate
  66. `operator.()' if that operator has been overloaded.  This means that if
  67. class `X' contains a member function `f()' but `X' overloads operator
  68. dot to return `Y&', then the following code
  69.  
  70.      X x;
  71.      x.f();
  72.  
  73. calls `Y::f()', not `X::f()'.
  74.  
  75.    Most of the time, this behaviour is exactly what you want.
  76. Sometimes however, you do want to access member functions of your smart
  77. reference class.  For example, suppose you have defined a class
  78. `DiskReference' which acts as a reference to data which is stored on
  79. disk.  The class caches the disk value in memory, and the cache is
  80. written back to the disk by the destructor.  Your class users may
  81. occaisionally want to explicitly flush the cache, so the `DiskReference'
  82. class should provide a class method `flush()' to do that.
  83.  
  84.    If you do want to access members of `DiskReference', then you need
  85. to do so without using the dot operator.  If the member(s) you want to
  86. access are overloaded operators, then you can just use the operator
  87. notation.  For other members, if you haven't overloaded `operator&()',
  88. you can use `(&x)->m'.  But it's often nice to overload operator& to
  89. return a smart pointer.  In this case, the best thing to do is to put
  90. most of the details of DiskReference in a base class, say
  91. DiskReferenceControl, which doesn't overload operator dot, and then
  92. invoke the members using a reference to DiskReferenceControl.  For
  93. example:
  94.  
  95.      foo(DiskReference& x) {
  96.          DiskReferenceControl& x_control(x);
  97.          x_control.flush();    // flushes x to disk
  98.      }
  99.  
  100. You could also simplify the calling of DiskReferenceControl member
  101. functions, using a helper function a function `control()' like this:
  102.  
  103.      inline DiskReferenceControl& control(DiskReference& x) { return x; }
  104.      
  105.      foo(DiskReference& x) {
  106.          control(x).flush();
  107.      }
  108.  
  109. -----------------------------------------------------------------------------
  110.  
  111. Another alternative not mentioned in the documentation is do just
  112. put all the relevant functions in the smart pointer, not the
  113. smart reference; if you need to invoke one of them on a smart
  114. reference, use the overloaded & operator to convert from a smart
  115. reference to a smart pointer: `(&x).foo();'.
  116.  
  117. >The -> operator has the advantage that it signals the delegation property
  118. >of the member selection when it's performed.  It's easy enough for the
  119. >programmer to ignore that aspect when it's adventageous for him to do so. 
  120. >It is also easy enough to identify that aspect when it is an issue.  "I
  121. >know this identifier is a reference or an object but here is this pointer
  122. >member selection operator being used so I know delegation is being used."
  123.  
  124. Overloadable operator -> is great, but it only gives you smart pointers,
  125. not smart references.  I think the approach outlined above has similar
  126. advantages of making it clear when delegated members are being selected
  127. and when the non-delegated members are being selected.  But the point of
  128. overloading . rather than -> it gives you smart references, not smart pointers.
  129.  
  130.  
  131. --
  132. Fergus Henderson                 WWW: http://www.cs.mu.oz.au/~fjh
  133. fjh@cs.mu.oz.au                  PGP: finger fjh@128.250.37.3
  134. ---
  135. [ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  136.   Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  137.   is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
  138.